package com.wondertek.service.service.business.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.wondertek.common.base.Result;
import com.wondertek.common.exception.AppException;
import com.wondertek.common.util.base.StringUtil;
import com.wondertek.common.util.security.LoginUser;
import com.wondertek.common.util.security.SecurityUtil;
import com.wondertek.service.dto.app.req.AddModeTimedTaskReq;
import com.wondertek.service.dto.app.req.AppRoomPageReq;
import com.wondertek.service.dto.app.req.AppRoomSelectByUserIdReq;
import com.wondertek.service.dto.app.req.AppRoomUpdateModeReq;
import com.wondertek.service.dto.app.res.AppRoomSelectByUserIdRes;
import com.wondertek.service.dto.app.res.DeviceErrorRecordKvRes;
import com.wondertek.service.dto.business.req.ModeTimedTaskFindReq;
import com.wondertek.service.dto.business.req.RoomAddReq;
import com.wondertek.service.dto.business.req.RoomPageReq;
import com.wondertek.service.dto.business.req.RoomUpdateReq;
import com.wondertek.service.dto.business.res.RoomPageRes;
import com.wondertek.service.dto.sys.req.SysJobAddReq;
import com.wondertek.service.dto.sys.req.SysJobUpdateReq;
import com.wondertek.service.entity.business.*;
import com.wondertek.service.entity.sys.SysJobPo;
import com.wondertek.service.mapper.business.AccessoryMapper;
import com.wondertek.service.mapper.business.RoomMapper;
import com.wondertek.service.mapper.business.RoomModeTimedTaskMapper;
import com.wondertek.service.sdk.iotdh.dto.req.AetAreaInfoReq;
import com.wondertek.service.sdk.iotdh.dto.req.ArmOptionsReq;
import com.wondertek.service.sdk.iotdh.dto.req.GetAreaInfosReq;
import com.wondertek.service.sdk.iotdh.dto.req.SetAreaArmModeReq;
import com.wondertek.service.sdk.iotdh.dto.res.ArmModesRes;
import com.wondertek.service.sdk.iotdh.dto.res.GetAreaArmModeRes;
import com.wondertek.service.sdk.iotdh.dto.res.SetAreaArmModeRes;
import com.wondertek.service.sdk.iotdh.service.DhDeviceService;
import com.wondertek.service.service.business.*;
import com.wondertek.service.service.sys.ISysJobService;
import com.wondertek.service.service.sys.impl.SysJobServiceImpl;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: qinjianhui
 * @create: 2024-07-17 15:43
 **/
@Service
public class RoomServiceImpl extends ServiceImpl<RoomMapper, RoomPo> implements RoomService {

    @Resource
    private RoomMapper roomMapper;

    @Resource
    private DeviceService deviceService;

    @Resource
    private DhDeviceService dhDeviceService;

    @Resource
    private AccessoryMapper accessoryMapper;

    @Resource
    private RentalService rentalService;

    @Autowired
    private ISysJobService jobService;

    @Autowired
    private RoomModeTimedTaskService roomModeTimedTaskService;

    @Autowired
    private RoomModeTimedTaskMapper roomModeTimedTaskMapper;

    /*
     * 根据设备查询分区
     * */
    @Override
    public List<RoomPo> selectByDevice(String id) {
        LambdaQueryWrapper<RoomPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoomPo::getDeviceId, id);
        wrapper.eq(RoomPo::getIsDelete, 0);
        return this.list(wrapper);
    }

    /*
     * 更改布防模式
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<SetAreaArmModeRes> updateMode(AppRoomUpdateModeReq req) {
        RoomPo room = this.getById(req.getRoomId());
        //拼接第三方需要的数据
        room.setMode(req.getMode());
        String deviceId = room.getDeviceId();
        DevicePo device = deviceService.getById(deviceId);
        SetAreaArmModeReq setAreaArmModeReq = new SetAreaArmModeReq();
        setAreaArmModeReq.setDeviceId(device.getSnCode());
        setAreaArmModeReq.setDevCode(device.getSkCode());
        setAreaArmModeReq.setArmMode(req.getMode());
        List<Integer> list = new ArrayList<>();
        list.add(room.getRoomCode());
        setAreaArmModeReq.setAreaIds(list);
        ArmOptionsReq armOptionsReq = new ArmOptionsReq();
        armOptionsReq.setProfile("Force");
        armOptionsReq.setTriggerId("test");
        armOptionsReq.setTriggerName("test");
        armOptionsReq.setClientAddress("127.0.0.1");
        setAreaArmModeReq.setArmOptions(armOptionsReq);
        //修改布防模式
        this.updateById(room);
        return dhDeviceService.setAreaArmMode(setAreaArmModeReq);
    }

    /*
     * 根据用户id查询房间
     * */
    @Override
    public List<AppRoomSelectByUserIdRes> selectByUserId(AppRoomSelectByUserIdReq req) {
        return roomMapper.selectByUserId(req);
    }

    /*
     * 房间列表
     * */
    @Override
    public Page<RoomPo> page(AppRoomPageReq req) {
        LambdaQueryWrapper<RoomPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoomPo::getDeviceId, req.getDeviceId());
        wrapper.eq(RoomPo::getIsDelete, 0);
        Page<RoomPo> page = this.page(new Page<>(req.getPageNo(), req.getPageSize()), wrapper);
        //查询站点
        List<RoomPo> list = page.getRecords();
        if (CollectionUtils.isNotEmpty(list)) {
            SitePo sitePo = roomMapper.selectSiteByRoom(list.get(0).getId());
            if (sitePo != null) {
                for (RoomPo roomPo : list) {
                    roomPo.setDescription(sitePo.getSiteName());
                }
            }
        }
        return page;
    }


    /*
     * 管理员新增房间
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRoom(RoomAddReq roomAddReq) {
        //校验房间名称是否在本网关下是否重复
        LambdaQueryWrapper<RoomPo> roomPoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomPoLambdaQueryWrapper.eq(RoomPo::getDeviceId, roomAddReq.getDeviceId());
        roomPoLambdaQueryWrapper.eq(RoomPo::getRoomName, roomAddReq.getRoomName());
        List<RoomPo> list1 = this.list(roomPoLambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(list1)) {
            throw new AppException("device.exist.room.name");
        }
        //查询该设备下分区编码的最大值
        Integer areaId = 1;
        LambdaQueryWrapper<RoomPo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoomPo::getDeviceId, roomAddReq.getDeviceId());
        wrapper.eq(RoomPo::getIsDelete, 0);
        wrapper.orderByDesc(RoomPo::getRoomCode);
        List<RoomPo> list = this.list(wrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            if (list.size() == 32)
                throw new AppException("room.max.value.32");
            //先去查询已删除的，重新把它启用
            List<RoomPo> roomPos = roomMapper.selectDeleteRoomByDeviceId(roomAddReq.getDeviceId());
            if (CollectionUtils.isNotEmpty(roomPos)) {
                RoomPo roomPo = roomPos.get(0);
                //先去启用
                AetAreaInfoReq aetAreaInfoReq = new AetAreaInfoReq();
                aetAreaInfoReq.setDeviceId(roomAddReq.getSnCode());
                aetAreaInfoReq.setAreaEnable(true);
                aetAreaInfoReq.setAreaName(roomAddReq.getRoomName());
                aetAreaInfoReq.setAreaId(roomPo.getRoomCode());
                dhDeviceService.setAreaInfo(aetAreaInfoReq);
                roomMapper.updateRoomDelete(roomPo.getId(), roomAddReq.getRoomName(), roomAddReq.getIndustryType());
                return;
            }
            RoomPo po = list.get(0);
            Integer roomCode = po.getRoomCode();
            if (roomCode != null) areaId = roomCode + 1;

        }
        RoomPo roomPo = new RoomPo();
        roomPo.setRoomName(roomAddReq.getRoomName());
        roomPo.setDeviceId(roomAddReq.getDeviceId());
        roomPo.setRoomCode(areaId);
        roomPo.setIsDelete(0);
        roomPo.setIndustryType(roomAddReq.getIndustryType());
        //查询房间的布防模式
        GetAreaInfosReq getAreaInfosReq = new GetAreaInfosReq();
        getAreaInfosReq.setAreaId(areaId);
        getAreaInfosReq.setDeviceId(roomAddReq.getSnCode());
        Result<GetAreaArmModeRes> areaArmMode = dhDeviceService.getAreaArmMode(getAreaInfosReq);
        List<ArmModesRes> armModes = JSONArray.parseArray(JSONObject.parseObject(String.valueOf(areaArmMode.getData())).get("armModes").toString(), ArmModesRes.class);
        if (CollectionUtils.isNotEmpty(armModes)) {
            roomPo.setMode(armModes.get(0).getMode());
        }
        //调用DH新增分区
        AetAreaInfoReq aetAreaInfoReq = new AetAreaInfoReq();
        aetAreaInfoReq.setDeviceId(roomAddReq.getSnCode());
        aetAreaInfoReq.setAreaEnable(true);
        aetAreaInfoReq.setAreaName(roomAddReq.getRoomName());
        aetAreaInfoReq.setAreaId(areaId);
        dhDeviceService.setAreaInfo(aetAreaInfoReq);
        this.save(roomPo);
    }

    /*
     * 房间列表
     * */
    @Override
    public Page<RoomPo> page(RoomPageReq roomPageReq) {
        LambdaQueryWrapper<RoomPo> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(roomPageReq.getRoomName())) {
            wrapper.or(i -> i.like(RoomPo::getRoomName, roomPageReq.getRoomName()));
        }
        wrapper.eq(RoomPo::getDeviceId, roomPageReq.getDeviceId());
        wrapper.eq(RoomPo::getIsDelete, 0);
        return this.page(new Page<>(roomPageReq.getPageNo(), roomPageReq.getPageSize()), wrapper);
    }

    /**
     * 查询网关设备-房间列表
     *
     * @param roomPageReq
     * @return
     */
    public Page<RoomPageRes> roomPage(RoomPageReq roomPageReq) {
        return roomMapper.roomPage(roomPageReq, new Page(roomPageReq.getPageNo(), roomPageReq.getPageSize()));
    }

    /*
     * 修改房间
     * */
    @Override
    public void updateRoom(RoomUpdateReq updateReq) {
        RoomPo roomPo = new RoomPo();
        BeanUtil.copyProperties(updateReq, roomPo);
        RoomPo byId = this.getById(updateReq.getId());
        if (!updateReq.getRoomName().equals(byId.getRoomName())) {
            LambdaQueryWrapper<RoomPo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(RoomPo::getRoomName, updateReq.getRoomName());
            lambdaQueryWrapper.eq(RoomPo::getDeviceId, byId.getDeviceId());
            List<RoomPo> list = this.list(lambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(list)) {
                throw new AppException("device.exist.room.name");
            }
        }
        this.updateById(roomPo);
    }

    /*
     * 删除房间  todo 确认有没有删除分区
     * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoom(String id) {
        //有配件不能删除
        LambdaQueryWrapper<AccessoryPo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AccessoryPo::getRoomId, id);
        List<AccessoryPo> list = accessoryMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            throw new AppException("room.exist.accessory");
        }
        //先查询是不是默认分区1
        RoomPo byId = this.getById(id);
        if (1 == byId.getRoomCode()) {
            throw new AppException("room.could.not.delete");
        }

        //检查该房间是否是租赁中
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        String dateStr = simpleDateFormat.format(date);
        LambdaQueryWrapper<RentalDevicePo> rentalLambdaQueryWrapper = new LambdaQueryWrapper<>();
        rentalLambdaQueryWrapper.eq(RentalDevicePo::getRoomId, id);
        rentalLambdaQueryWrapper.eq(RentalDevicePo::getIsDelete, 0);
        //  rentalLambdaQueryWrapper.apply("start_date < '"+dateStr+"'");
        rentalLambdaQueryWrapper.apply("end_date > '" + dateStr + "'");
        List<RentalDevicePo> rentalList = rentalService.list(rentalLambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(rentalList)) {
            throw new AppException("room.is.rental");
        }
        //改为撤防
        RoomPo roomPo = new RoomPo();
        roomPo.setId(id);
        roomPo.setMode("D");
        this.updateById(roomPo);
        AppRoomUpdateModeReq appRoomUpdateModeReq = new AppRoomUpdateModeReq();
        appRoomUpdateModeReq.setRoomId(id);
        appRoomUpdateModeReq.setMode("D");
        this.updateMode(appRoomUpdateModeReq);
        //设置分区禁用
        this.removeById(id);
    }

    /*
     * 用户查询房间数
     * */
    public int selectRoomNumByUserId(String userId) {
        //roomMapper
        return 0;
    }

    @Override
    public Page<AppRoomSelectByUserIdRes> findRoomByDcId(AppRoomPageReq req) {

        LoginUser loginUser = SecurityUtil.getLoginUser();

        String userId = loginUser != null ? loginUser.getUserId() : null;

        if (StringUtil.isEmpty(userId))
            throw new AppException("user.id.not.null");

        return roomMapper.findRoomByDcId(req.getDeviceId(), userId, new Page<>(req.getPageNo(), req.getPageSize()));
    }

    /**
     * 新增定时布撤防任务
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addModeTimedTask(AddModeTimedTaskReq req) {

        String cron = "";

        String[] split = req.getTime().split(":");

        for (int i = split.length - 1; i >= 0; i--) {
            cron += split[i] + " ";
        }

        cron += "? * ";

        cron += req.getWeek();

        System.out.println(cron);

        if (!CronExpression.isValidExpression(cron))
            throw new AppException("cron格式错误");

        SysJobAddReq sysJobAddReq = new SysJobAddReq();
        sysJobAddReq.setJobName(req.getName());
        sysJobAddReq.setInvokeTarget("modeTimedTask.addModeTimedTask(com.wondertek.service.dto.app.req.AppRoomUpdateModeReq-{\"roomId\":\"" + req.getRoomId() + "\",\"mode\":\"" + req.getMode() + "\"})");

        sysJobAddReq.setCronExpression(cron);

        //     sysJobAddReq.setDescription(new Gson().toJson(req));

        //  System.out.println("回显---");
        //   System.out.println(sysJobAddReq.getDescription());


        RoomModeTimedTaskPo roomModeTimedTaskPo = new RoomModeTimedTaskPo();
        BeanUtil.copyProperties(req, roomModeTimedTaskPo);


        // 有任务id表示修改
        if (!StringUtil.isEmpty(req.getTaskId())) {
            SysJobUpdateReq sysJobUpdateReq = new SysJobUpdateReq();
            BeanUtil.copyProperties(sysJobAddReq, sysJobUpdateReq);
            sysJobUpdateReq.setId(req.getTaskId());
            jobService.updateSysJob(sysJobUpdateReq);
            roomModeTimedTaskService.updateById(roomModeTimedTaskPo);
        } else { // 新增

            String taskId = jobService.add(sysJobAddReq);

            roomModeTimedTaskPo.setTaskId(taskId);

            roomModeTimedTaskService.save(roomModeTimedTaskPo);
        }


    }

    @Override
    public void updModeTimedTask(AddModeTimedTaskReq req) {
        if (StringUtil.isEmpty(req.getId()) || StringUtil.isEmpty(req.getTaskId()))
            throw new AppException("id或taskId为空!");

        this.addModeTimedTask(req);

    }

    @Override
    public Page<AddModeTimedTaskReq> findModeTimedTask(ModeTimedTaskFindReq modeTimedTaskFindReq) {

        return roomModeTimedTaskMapper.findModeTimedTask(new Page<>(modeTimedTaskFindReq.getPageNo(), modeTimedTaskFindReq.getPageSize()));

    }

    @Override
    public void onOffModeTimedTask(String taskId, Integer status) {
        if (status == 0)
            jobService.resumeJob(taskId);
        else
            jobService.pauseJob(taskId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delModeTimedTas(String taskId) {
        LambdaQueryWrapper<RoomModeTimedTaskPo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(RoomModeTimedTaskPo::getTaskId, taskId);
        roomModeTimedTaskService.remove(lambdaQueryWrapper);

        jobService.removeJobById(taskId);
    }
}

